#include <windows.h>
#include <string.h>
#include <wincon.h>
#include <string.h>
#include <malloc.h>
#include <stdio.h>
#include <conio.h>
#include <time.h>

#include "AsciiImages.h"
#include "Utils.h"

#pragma warning (disable: 4996)

COORD coord = {80, 25}, coord2 = {0, 0};	// Coordinates used for "blit" operations
SMALL_RECT write = {0, 0, 79,24};			// Region to write to
SMALL_RECT fill_rect = {20,13,60,23};

const char* Password_Words[] = {"ALPHA","TANGO","FOXTROT"}; //Password words.

//------------------Begining of constant main menu strings-------------------
const char *mainstrings[MenuSize]={
							"Client Menu",
							"Property Menu ",
							"Save To Files",
							"Matching Menu",
							"Reports",
							"Exit"
							};

const char *clientstrings[MenuSize]={
							"Add New Client",
							"Update Client",
							"Delete Client",
							"Show Clients",
							"Find Client",
							"Back To Main"
							};

const char *clientfieldstrings[ClientFieldsLength]={
							"ID",
							"Name",
							"Family",
							"City",
							"Street",
							"Phone",
							"Active",
							"Gender",
							"Demands"
							};

const char *ActiveStrings[ActiveStringsLength]={
							"Activate",
							"Disable"
							};

const char *GenderStrings[ActiveStringsLength]={
							"Male",
							"Female"
							};

const char *EasterStrings[EasterStringsLength]={
							"Delete Clients",
							"Delete Properties"
							};

const char *SearchClientStrings[SearchClientLength]={
							"Search By ID",
							"Search By Name",
							"Search By Phone"
							};

const char *DemandClientStrings[DemandClientLength]={
							"Demand Kind",
							"Demand Type",
							"Demand Price",
							"Demand City",
							"Demand Rooms"
							};

const char *DPKindStrings[DPKindLength]={
							"House",
							"Apartment",
							"Shop"
							};

const char *DPDemandTypeStrings[ActiveStringsLength]={
							"Buy",
							"Rent"
							};

const char *DPPropertyTypeStrings[ActiveStringsLength]={
							"Sell",
							"To Rent"
							};

const char *DemandEditStrings[ActiveStringsLength]={
							"Add Demand",
							"Delete Demand"
							};

const char *ReportsStrings[ReportsStringsLength]={
							"Sort Client Demands",
							"Sort Clients By ID",
							"Sort Clients By Name",
							"Demands List By Client",
							"Properties On Text File",
							"Properties By Name On Text File"
							};
const char *SortClientDemandFields[SortClientDemandFieldsLength]={
							"Sort By Price",
							"Sort By City",
							"Sort By Kind"
							};

const char *PropertiesStrings[PropertiesStringsLength]={
							"Add New Property",
							"Update Property",
							"Delete Property",
							"Show Properties",
							"Find Property",
							"Back To Main"
							};

const char *PropertiesFields[PropertiesFieldsLength]={
							"Property Kind",
							"Property Type",
							"Property City",
							"Property Rooms",
							"Property Price",
							"Property Activation",
							"Contact 1 Name",
							"Contact 1 Phone",
							"Contact 2 Name",
							"Contact 2 Phone"
							};

const char *PropertiesFieldsSearch[ActiveStringsLength]={
							"Search By City",
							"Search By Kind"
							};
const char *MatchingStrings[MathingStringsLength]={
							"Match Client To Properties",
							"Match Property To Clients",
							"Match Clients To Properties"
};
//------------------------------------------------------------------------
// Gray screen by value.
void GrayScreen(int C)
{
HANDLE hnd;
CHAR_INFO buf[25*80];
int i,j;

hnd = GetStdHandle(STD_OUTPUT_HANDLE);
ReadConsoleOutputA(hnd,(PCHAR_INFO)&buf,coord,coord2,&write);
for(i=0;i<=24;i++)
	for(j=0;j<=79;j++)
			buf[80*i + j].Attributes |=(255 - C) ;

WriteConsoleOutputA(hnd, (const CHAR_INFO *)(&buf), coord, coord2, &write);

}

//Shows Horizontal menu from array received, return index of selection.
byte menu_hor(const char *Arr[],int size,int starti,char *Header,int StartX)
{
char ch;
int i,ind = starti,RealX;

if (StartX>=0)
	RealX = StartX;
else
{
	RealX=0;
	for(i=0;i<size;i++)
		RealX+=(int)strlen(Arr[i]) + 2;
	RealX+=2 + 1;
	RealX = 40 - (RealX)/2;
}
showinputimage(0);

settextcolor(0x0f);
gotoxy(40 - ((int)strlen(Header))/2,12);
printf("%s",Header);
do
{
gotoxy(RealX,14);
printf("(");
for(i=0;i<size;i++)
  {
	if (i==ind)
		settextcolor(0x4f);
	else
		settextcolor(0x0f);

	  printf(" %s ",Arr[i]);
	  settextcolor(0x0f);
	  
	  if (i<size-1)
		printf("|");

  }//end for
printf(")");

ch = getch();
if (ch==0,ch==77)
	ind++;

if (ch==0,ch==75)
	ind--;

if (ind>=size)
	ind = 0;
if (ind<0)
	ind = size-1;

}
while (ch!=27 && ch!=13);

return (ch==27)?(255):(ind);
}
//Randomally fade out chars on exit.
void fadeonquit()
{
int x=0,y=0,counter=0;
int mat[80][25]={0};
srand((unsigned int)time(NULL));
while (counter <= (80*25)-2)
{
		x = (rand() % 80);
		y = (rand() % 25);

		while (x==79 && y==24)
	{
		x = (rand() % 80);
		y = (rand() % 25);
	}
 
if (mat[x][y]==0)
{
	mat[x][y]=1;
	gotoxy(x,y);
	printf("%c",' ');
	counter++;
}
if (counter % 500 == 0)
	Sleep(1);

}
system("cls");
}

//put number on screen with many options.
void putnumber(int num,int x,int y,int clr,int mid,int delsize,char *c1,char *c2)
{
char BUF[20],BUF2[20];
strcpy(BUF2,"");
ltoa(num,BUF,10);
if (c1)
	strcat(BUF2,c1);
strcat(BUF2,BUF);
if (c2)
	strcat(BUF2,c2);
puttext(BUF2,x,y,clr,mid,delsize);
}
//put text on screen with many options.
void puttext(char *str,int x,int y,int clr,int mid,int delsize)
{
int x0;
	if (mid)
	{
		x0 = 1 + x - (int)strlen(str)/2;
		fillascii(x - delsize/2,y,x+delsize/2,y,' ',0x00);
	}
	else
	{
		x0=x;
		fillascii(x0,y,x0+delsize,y,' ',0x00);
	}
	
	
	
gotoxy(x0,y);
settextcolor(clr);
printf(str);
}

//Faded confirmation message with need to press any key.
void ConfirmationMessage(char *Message)
{
HANDLE hnd;
CHAR_INFO org[25*80];

hnd = GetStdHandle(STD_OUTPUT_HANDLE);
	ReadConsoleOutputA(hnd,(PCHAR_INFO)&org,coord,coord2,&write);
	GrayScreen(128);
showcursor(FALSE);
fillascii(15,11,65,15,' ',0x00);
settextcolor(0x0c);
box(15,11,66,15);
gotoxy(40 - (int)strlen(Message)/2,12);
settextcolor(0x0f);
printf("%s",Message);
gotoxy(40-15 + 1,13);
printf("Press any key To continiue... ");

getch();

WriteConsoleOutputA(hnd, (const CHAR_INFO *)(&org), coord, coord2, &write);

}
//faded message with Yes\No Question on exit.
int AskYesNoQuestion(char *Question)
{
HANDLE hnd;
CHAR_INFO org[25*80];
char ch=0;

hnd = GetStdHandle(STD_OUTPUT_HANDLE);
	ReadConsoleOutputA(hnd,(PCHAR_INFO)&org,coord,coord2,&write);
	GrayScreen(128);
showcursor(FALSE);
fillascii(15,11,65,15,' ',0x00);
settextcolor(0x0c);
box(15,11,66,15);
gotoxy(40 - (int)strlen(Question)/2,12);
settextcolor(0x0f);
printf("%s",Question);
gotoxy(40-5 + 1,13);
printf("(Yes\\No)");

while (ch!='y' && ch!='n' && ch!='Y' && ch!='N')
	ch = getch();

WriteConsoleOutputA(hnd, (const CHAR_INFO *)(&org), coord, coord2, &write);

return ((ch=='y') || (ch=='Y'));
}

//Fill Ascci chars with many options.
void fillascii(int x0,int y0,int x1,int y1,char chr,char clr)
{
HANDLE hnd;
CHAR_INFO buf[25*80];
int i,j;
hnd = GetStdHandle(STD_OUTPUT_HANDLE);
ReadConsoleOutputA(hnd,(PCHAR_INFO)&buf,coord,coord2,&write);

for(i=y0;i<=y1;i++)
	for(j=x0;j<=x1;j++)
	{
		buf[80*i + j].Char.UnicodeChar = chr;
		buf[80*i + j].Attributes = clr;
	}
WriteConsoleOutputA(hnd, (const CHAR_INFO *)(&buf), coord, coord2, &write);

}
//print the main menu ascii image.
void showmainmenu(int flag)
{
	CHAR_INFO *s1,*s2;
	
	if (flag)
		s1 = PushScreen();

	plotasciiimage(Menu_Image,0,0,Menu_Image_WIDTH,Menu_Image_DEPTH,0,Menu_Image_WIDTH);

	if (flag)
	{
	s2 = PushScreen();
	PopScreen(s1);
	fadetoscreen(s2);
	free(s2);
	}

}
//shows the input image.
void showinputimage(int flag)
{
	CHAR_INFO *s1,*s2;
	if (flag)
		s1 = PushScreen();

	plotasciiimage(INPUT_IMAGE,0,0,INPUT_IMAGE_WIDTH,INPUT_IMAGE_DEPTH,0,INPUT_IMAGE_WIDTH);

	if (flag)
	{
	s2 = PushScreen();
	PopScreen(s1);
	fadetoscreen(s2);
	free(s2);
	}
}
//Shows output image with random dots inside.
void showoutputimage(int flag)
{
int x,y,i;
CHAR_INFO *s1,*s2;

if (flag)
	s1 = PushScreen();
plotasciiimage(OUTPUT_IMAGE,0,0,OUTPUT_IMAGE_WIDTH,OUTPUT_IMAGE_DEPTH,0,OUTPUT_IMAGE_WIDTH);

srand((unsigned)time(NULL));
for(i=0;i<100;i++)
{
	x = (rand() % (76 - 3 + 1)) + 3; 
	y = (rand() % (23 - 2 + 1)) + 2; 
	settextcolor((x+y)%15);
	gotoxy(x,y);
	printf(".");
}
if (flag)
{
s2 = PushScreen();
PopScreen(s1);
fadetoscreen(s2);
free(s2);
}
}

//Function to print image from array to screen.
void plotasciiimage(unsigned char Arr[],int x0,int y0,int sizex,int sizey,int min_x,int max_x)
{
CHAR_INFO chars[80*25];						// Character buffer
char ch;
int i,j;
HANDLE wHnd;
wHnd = GetStdHandle(STD_OUTPUT_HANDLE);

ReadConsoleOutputA(wHnd,(PCHAR_INFO)&chars,coord,coord2,&write);

for(i=0;i<coord.Y;i++)
for(j=0;j<coord.X;j++)
{
//	chars[i*coord.X + j].Char.AsciiChar=' ';
//	chars[i*coord.X + j].Attributes = 0x0000;
}

x0-=min_x;

for(i=0;i<sizey;i++)
	for(j=0;j<sizex;j++)
	{
		if (j>=min_x && j<max_x)
		{
		ch=Arr[i*sizex*2 +j*2];
		chars[(i+y0)*coord.X + x0 + j].Char.UnicodeChar=ch;
		ch=Arr[i*sizex*2 +j*2+1];
		chars[(i+y0)*coord.X + x0+ j].Attributes = ch;
		}
	}

	WriteConsoleOutputA(wHnd, (const CHAR_INFO *)(&chars), coord, coord2, &write);
}

//Main universal and only one method to inut value from user.
// has many options, can block unwanted chars, can block max size,
// showing title, return exit codes.
char *readvalue(char *title,char *range,int masked,int maxsize,char *msg)
{
char *tmpstr=NULL,ch,i;
int count=0,x1,y1=13;

showinputimage(0);

if (msg!=NULL)
{
x1 = 40 - (int)strlen(msg) / 2 + 1;
puttext(msg,x1,y1+2,0x0c,0,0);
}

puttext(title,20,y1,0x0f,0,0);
x1 = (int)strlen(title) + 20;

showcursor(TRUE);
tmpstr = (char*)malloc(sizeof(char)*50);
strcpy(tmpstr,"");
settextcolor(0x000c);// string red
do
{
ch=getch();
if (count<maxsize)
  if (strchr(range,ch)!=NULL)
	{	
		count++;
		//tmpstr = (char*)realloc(tmpstr,sizeof(char)*(count+1));
        tmpstr[count-1]=ch;
		tmpstr[count]=0;
		gotoxy(x1,y1);
		if (!masked) printf("%s",tmpstr);
		else
			for(i=0;i<(int)strlen(tmpstr);i++)
				printf("*");
	}
 if (ch==8 && count>0)
   {
		count--;
		tmpstr[count]=' ';
		gotoxy(x1,y1);
		if (!masked)
			printf("%s",tmpstr);
		else
		{
			for(i=0;i<(int)strlen(tmpstr)-1;i++)
				printf("*");
				printf(" ");
		}

		//tmpstr = (char*)realloc(tmpstr,sizeof(char)*(count+1));
		tmpstr[count]=0;
		gotoxy(x1,y1);
		if (!masked) printf("%s",tmpstr);
		else
			for(i=0;i<(int)strlen(tmpstr);i++)
				printf("*");
   }

 if (ch==27)
	 if(!AskYesNoQuestion("Are you want to exit ?"))
	 {
		 ch=0;
  		 gotoxy(x1+(int)strlen(tmpstr),y1);
		 settextcolor(0x000c);// string red
		 showcursor(TRUE);
	 }
	 if (ch==13)
		 if ((int)strlen(tmpstr)>0)
			 break;

}

while (ch!=27);

showcursor(FALSE);
if (count==0 || ch==27)
{
	if (ch==27 && (int)strlen(tmpstr)>0)
		free(tmpstr);
	return NULL;
}
else
	return tmpstr;

}
//Universal Main Menu function that print menu on every array received.
// print the manu, enable user to choise the line, and return the index
//of the line selected.has many options.(toggle supported)
int menu(const char *Arr[],int size,int starti,char *Header,int StartY)
{
char ch;
int ind=starti,passindex=0,offset=0;
char passbuffer[20];
strcpy(passbuffer,EASTER);

if (Arr==mainstrings || Arr==clientstrings || Arr==PropertiesStrings)
	showmainmenu(0);
else
	showoutputimage(0);

placemenu(Arr,size,StartY,starti,Header,0);
do
{

ch = getch();
 
if (ch==27 || ch==13)
	break;

if (ch==0,ch==72)
	{
		ind--;
		if (ind<0)
			ind=size-1;
		offset = (ind>MaxMenuLength-1)?(ind-(MaxMenuLength-1)):(0);
		placemenu(Arr,size,StartY,ind,Header,offset);
	}
if (ch==0,ch==80)	
	{
		ind++;
		if (ind>=size)
			ind = 0;

		offset = (ind>MaxMenuLength-1)?(ind-(MaxMenuLength-1)):(0);
		placemenu(Arr,size,StartY,ind,Header,offset);
	}



if (toupper(ch)==toupper(passbuffer[passindex]))
	passindex++;
else
	passindex=0;

if (passindex == (int)strlen(EASTER))
		{
			passindex = 0;
			passindex = menu_hor(EasterStrings,EasterStringsLength,passindex,"Select Admin Operation: ",-1);
			switch (passindex)
			{
				case 0: DeleteClientsFile();break;
				case 1: DeletePropertiesFile();break;
			}
			showmainmenu(1);
			placemenu(Arr,size,StartY,ind,Header,0);
			passindex=0;
		}

}
while(ch!=27 && ch!=13);

if (ch==27)
	return -1;
else
	return ind;

}
// not in use in this project
int menu_old(const char *Arr[],int size,int starti,char *Header,int StartY)
{

 HANDLE rHnd;
 DWORD numEvents = 0;
 DWORD numEventsRead = 0;
 BOOL appIsRunning = TRUE;
 INPUT_RECORD *eventBuffer;
 int i,ind=starti,passindex=0;
 char passbuffer[20];
 strcpy(passbuffer,EASTER);
 
   rHnd = GetStdHandle( STD_INPUT_HANDLE );
    // If we set appIsRunning to false, the program will end!
   //fillascii(fill_rect.Left,fill_rect.Top,fill_rect.Right,fill_rect.Bottom,' ',0x00);
   //placemenu(Arr,size,StartY,ind,Header);

    while (appIsRunning) {

        // Find out how many console events have happened:
        GetNumberOfConsoleInputEvents(rHnd, &numEvents);

        // If it's not zero (something happened...)
        if (numEvents!=0) {

            // Create a buffer of that size to store the events
            //INPUT_RECORD *eventBuffer = new INPUT_RECORD[numEvents];
			eventBuffer = (INPUT_RECORD*)malloc(numEvents*sizeof(INPUT_RECORD));
            // Read the console events into that buffer, and save how
            // many events have been read into numEventsRead.
            ReadConsoleInput(rHnd, eventBuffer, numEvents, &numEventsRead);

            // Now, cycle through all the events that have happened:
            for (i=0; i<(int)numEventsRead; ++i) {

                // Check the event type: was it a key?
                if (eventBuffer[i].EventType==KEY_EVENT)
					if (eventBuffer[i].Event.KeyEvent.bKeyDown==TRUE)
					{

                    // Yes! Was the key code the escape key?
                    if (eventBuffer[i].Event.KeyEvent.wVirtualKeyCode==VK_ESCAPE) {
                        // Yes, it was, so set the appIsRunning to false.
                        appIsRunning = FALSE;
                    }
					switch (eventBuffer[i].Event.KeyEvent.wVirtualKeyCode)
					{
					case VK_DOWN:ind++;break;
					case VK_UP:ind--;break;
					case VK_RETURN: appIsRunning = FALSE;break;
					case VK_ESCAPE: {appIsRunning = FALSE;ind=-1;break;}
					default:{
							if (eventBuffer[i].Event.KeyEvent.wVirtualKeyCode==(WORD)(toupper(passbuffer[passindex])))
								passindex++;
							else
								passindex=0;

							if (passindex == (int)strlen(EASTER))
									{
										passindex = 0;
										passindex = menu_hor(EasterStrings,EasterStringsLength,passindex,"Select Admin Operation: ",-1);
										switch (passindex)
										{
										case 0: DeleteClientsFile();break;
										case 1:break;
										}
									   //showmainmenu();
									   passindex=0;
									}
							}
					};
					if (appIsRunning)
					{
						if (ind>=size)
							ind=0;
						if(ind<0)
							ind=size-1;

						//placemenu(Arr,size,StartY,ind,Header);
					}
                }
            }
            // Clean up our event buffer:
			free(eventBuffer);
			eventBuffer = NULL;
        }
    }
return ind;
    // Exit
}

// print box. I think not un use anymore.
void box(int x1,int y1,int x2,int y2)
{
int i;
fillascii(x1+1,y1+1,x2-1,y2-1,' ',0x00);
for (i=x1;i<x2;i++)
{
 gotoxy(i,y1);
 settextcolor(0x0007);
 printf("%c",LineX);
 gotoxy(i,y2);
 printf("%c",LineX);
}
for (i=y1;i<y2;i++)
{
 gotoxy(x1,i);
 settextcolor(0x0007);
 printf("%c",LineY);
 gotoxy(x2,i);
 printf("%c",LineY);
}

gotoxy(x1,y1);
printf("%c",Line1);
gotoxy(x2,y1);
printf("%c",Line2);
gotoxy(x2,y2);
printf("%c",Line3);
gotoxy(x1,y2);
printf("%c",Line4);

}

//clear screen
void clrscr()
{
		settextcolor(0);
		system("cls");
}
//Show or hide the edit cursor
void showcursor(BOOL a)
{
HANDLE hConsoleOutput;
CONSOLE_CURSOR_INFO structCursorInfo;

hConsoleOutput = GetStdHandle( STD_OUTPUT_HANDLE );

structCursorInfo.dwSize = 10;
structCursorInfo.bVisible = a;

SetConsoleCursorInfo( hConsoleOutput,&structCursorInfo );
}

//set the background color.
void setbackgroundcolor(char *clr)
{
char c[20];
strcpy(c,"color ");
strcat(c,clr);
system(c);
}
//set text color.
void settextcolor(int color)
{
 HANDLE  hColor;	
 hColor = GetStdHandle (STD_OUTPUT_HANDLE);
 SetConsoleTextAttribute(hColor,color);
 
}
//goind to certain position in console.
void gotoxy(int x,int y)
{
HANDLE console_handle;
COORD cursor_coord;
DWORD actual=0;

cursor_coord.X=x;
cursor_coord.Y=y;

console_handle= GetStdHandle( STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(console_handle,cursor_coord);
}
//calc the max string in menu
int getmaxmenulength(const char *A[],int size)
{
int i;
int max=0;
for(i=0;i<size;i++)
  if ((int)strlen(A[i])>max)
	  max = (int)strlen(A[i]);

return max;
}

//Addition method of placeing the universal menu and print it on screen.
//toggle supported by offset value, has many options.
void placemenu(const char *Arr[],int size,int ystart,int index,char *header,int offset)
{
	int maxstringlength;
	int x0,x1,y0,y1,i,j,xt;
	char tmpstr[50];
	int menusize;
	menusize = (size>MaxMenuLength)?(MaxMenuLength):(size);
	maxstringlength = getmaxmenulength(Arr,size)+2;
	x0 = 40-(maxstringlength/2) ;
	x1 = 40+(maxstringlength/2)+1 ;
	y0 = ystart -1;
    y1 = ystart + menusize;
	settextcolor(0x0007);
	box(x0,y0,x1,y1);
	for(i=0;i<menusize;i++)
	{
	strcpy(tmpstr,"");
	xt = 40 - (int)strlen(Arr[i+offset])/2 + 1;
	for(j=x0;j<xt-1;j++)
		strcat(tmpstr," ");
	strcat(tmpstr,Arr[i+offset]);
	for(j=xt+(int)strlen(Arr[i+offset]);j<x1;j++)
		strcat(tmpstr," ");

	gotoxy(x0+1,ystart+i);
	
	if ((index!=i+offset))
		settextcolor(0x0007);
	else
		settextcolor(0x0070);

	printf("%s",tmpstr);
	}

	if (strlen(header)>0)
	{
		y0=ystart-1;
		x0 = 40 - ((int)strlen(header)+4)/2 + 1;
		settextcolor(0x0e);
		gotoxy(x0,y0);
		printf("[ %s ]",header);
	}

settextcolor(0x0007);
	
}
//Delete clients file
void DeleteClientsFile()
{
	if (remove(ClientsFile)==0)
		ConfirmationMessage("File Deleted.");
	else
		ConfirmationMessage("File Not Deleted.");
}
//Delete properties file.
void DeletePropertiesFile()
{
	if (remove(PropertiesFile)==0)
		ConfirmationMessage("File Deleted.");
	else
		ConfirmationMessage("File Not Deleted.");
}
// print ascii man
void printman(int x,int y)
{
	settextcolor(0x07);
	box(x-1,y-1,x-1 + MAN_WIDTH + 2,y-1 + MAN_DEPTH + 2);
	plotasciiimage(MAN,x,y,MAN_WIDTH,MAN_DEPTH,0,MAN_WIDTH);
}
// print ascii woman.
void printwoman(int x,int y)
{
	settextcolor(0x07);
	box(x-2,y-1,x-2 + WOMAN_WIDTH + 2,y-1 + WOMAN_DEPTH + 2);
	plotasciiimage(WOMAN,x,y,WOMAN_WIDTH,WOMAN_DEPTH,0,WOMAN_WIDTH);
}

//check the password algorithm
int CheckPassword(char *msg)
{
char *tmp,BUF[5],BUF2[20];
int count,starti,sum=0,i,j,found=0;
tmp = readvalue("Enter Password: ",TEXT_S,1,10,msg);
if (tmp==NULL)
{
	return 2;//empty
}

count = sizeof(Password_Words) / sizeof(Password_Words[0]);

for(i=0;i<count;i++)
	for(j=0;j<(int)strlen(Password_Words[i]);j++)
		sum += GetBitCount(Password_Words[i][j]);

ltoa(sum,BUF,10);
if ((int)strlen(BUF)>=(int)strlen(tmp))
{
	free(tmp);
	return 0;
}

strcpy(BUF2,tmp);
BUF2[strlen(tmp)-strlen(BUF)]=0;

for(i=0;i<count;i++)
	if (strstr(Password_Words[i],BUF2)!=NULL)
	{
		found=1;
		break;
	}

if (!found)
{
	free(tmp);
	return 0;
}
found=0;
starti=(int)strlen(tmp)-(int)strlen(BUF);
for(i=starti;i<(int)strlen(tmp);i++)
	if (tmp[i]!=BUF[i-starti])
	{
		found=1;
		break;
	}
if (found)
{
	free(tmp);
	return 0;
}

free(tmp);
return 1;
}

//count bits in the password words.
int GetBitCount(char ch)
{
int mask,i,count=0;
for(i=0;i<8;i++)
{
	mask = 1<<i;
	count += (mask & ch)?(1):(0);
}
return count;

}

//Main check password function.exit after 3 attempts.
int UserCheckPassword()
{
   int res=0,j=3;
	
   res = CheckPassword(NULL); 
   if(res==2)
	   return 0;
   if (res==0)
   {
	   while (j-->0)
		   if ((res=CheckPassword("Not Valid Password"))>0)
			   break;
   }
   if(j<0 || res==2)
	   return 0;
return 1;

}

//Nice ascii font conversion. print number. p = percentage.
void PutFontNumber(int x,int y,char *num,int P)
{
int i;
char ch;

for(i=0;i<(int)strlen(num);i++)
{
	ch = num[i]-'0';
	plotasciiimage(NUMFONT,x + i*5 + i*2,y,55,3,ch*5,ch*5+5);
}
if (P) // P = Percentage Sign
	plotasciiimage(NUMFONT,x + i*5 + i*2,y,55,3,50,55);

}

//Screen feature to save console ascii state before any change. return
//ascii info array of the screen.
CHAR_INFO* PushScreen()
{
CHAR_INFO *I;
HANDLE hnd;

I = (CHAR_INFO*)malloc(sizeof(CHAR_INFO)*(25*80));
hnd = GetStdHandle(STD_OUTPUT_HANDLE);
ReadConsoleOutputA(hnd,(PCHAR_INFO)I,coord,coord2,&write);

return I;
}

//Return back(restore) the ascii console state of the screen as it
//was before, or called with push command.
void PopScreen(CHAR_INFO *INFO)
{
HANDLE hnd;

hnd = GetStdHandle(STD_OUTPUT_HANDLE);

WriteConsoleOutputA(hnd, (const CHAR_INFO *)(INFO), coord, coord2, &write);

free(INFO);
}

//fade to screen transfer new ascii buffer array in the current
//ascii screen, to achieve simple page effect tranformation.
void fadetoscreen(CHAR_INFO *s1)
{
int x=0,y=0,counter=0;
int mat[80][25]={0};

/*srand((unsigned int)time(NULL));
while (counter <= (80*25)-2)
{
		x = (rand() % 80);
		y = (rand() % 25);

		while (x==79 && y==24)
	{
		x = (rand() % 80);
		y = (rand() % 25);
	}
 
if (mat[x][y]==0)
{
	mat[x][y]=1;
	settextcolor(s1[y*80+x].Attributes);
	gotoxy(x,y);
	printf("%c",s1[y*80+x].Char.UnicodeChar);
	counter++;
}
if (counter % 100 == 0)
	Sleep(1);

}

*/

for (y=0;y<25;y++)
	for(x=0;x<80;x++)
	{
		if (x!=79 && y!=24)
		{
		settextcolor(s1[y*80+x].Attributes);
		gotoxy(x,y);
		printf("%c",s1[y*80+x].Char.UnicodeChar);
		}	
	}
}
// Call back to use in every main function, to show the main menu.
void MainMenuFadeCallBack()
{
	showmainmenu(1);
}
DWORD WINAPI StartThread(LPVOID iValue)
{
	char *s = malloc(2);
	s[0] = (char)BlockChar;
	s[1] = 0;
	Sleep(3000);
while (1)
{
	//restore
	puttext(s,37,3,0x04,0,0);
	puttext(s,38,3,0x04,0,0);
	puttext(s,37,4,0x04,0,0);
	puttext(s,38,4,0x04,0,0);
	puttext(s,44,3,0x04,0,0);
	puttext(s,45,3,0x04,0,0);
	puttext(s,44,4,0x04,0,0);
	puttext(s,45,4,0x04,0,0);

	puttext(s,35,3,0x00,0,0);
	puttext(s,36,3,0x00,0,0);
	puttext(s,35,4,0x00,0,0);
	puttext(s,36,4,0x00,0,0);
	puttext(s,42,3,0x00,0,0);
	puttext(s,43,3,0x00,0,0);
	puttext(s,42,4,0x00,0,0);
	puttext(s,43,4,0x00,0,0);
	Sleep(2000);
	//restore
	puttext(s,35,3,0x04,0,0);
	puttext(s,36,3,0x04,0,0);
	puttext(s,35,4,0x04,0,0);
	puttext(s,36,4,0x04,0,0);
	puttext(s,42,3,0x04,0,0);
	puttext(s,43,3,0x04,0,0);
	puttext(s,42,4,0x04,0,0);
	puttext(s,43,4,0x04,0,0);

	puttext(s,37,3,0x00,0,0);
	puttext(s,38,3,0x00,0,0);
	puttext(s,37,4,0x00,0,0);
	puttext(s,38,4,0x00,0,0);
	puttext(s,44,3,0x00,0,0);
	puttext(s,45,3,0x00,0,0);
	puttext(s,44,4,0x00,0,0);
	puttext(s,45,4,0x00,0,0);

	Sleep(2000);
}

return 0;
}
